package com.shuwen.gcdj.common.aop;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import com.shuwen.gcdj.common.util.http.IpUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author hf
 *
 */
@Aspect
@Component
public class RequestAspect {

	/**
	 * 指定切点 匹配 com.example.demo.controller包及其子包下的所有类的所有方法
	 */
	@Pointcut("execution(public * com.shuwen.gcdj.controller..*.*Controller.*(..))")
	public void webLog() {
	}

	/**
	 *
	 * @param joinPoint
	 */
	@Before("webLog()")
	public void doBefore(JoinPoint joinPoint) {
		try {
			HttpServletRequest request = (HttpServletRequest) RequestContextHolder.getRequestAttributes().resolveReference(RequestAttributes.REFERENCE_REQUEST);
			String executeClass = joinPoint.getTarget().getClass().getName();
			String executeMethod = joinPoint.getSignature().getName() + "()";
			String lineSeparator = "\n";
			StringBuilder sb = new StringBuilder(1000);
			sb.append(lineSeparator);
			sb.append("*********************************请求信息开始***************************************");
			sb.append(lineSeparator);
			sb.append("请求URL:").append(request.getRequestURL().toString());
			sb.append(lineSeparator);
			sb.append("请求类型:").append(request.getMethod());
			sb.append(lineSeparator);
			sb.append("请求IP:").append(IpUtils.getRemoteAddr(request));
			sb.append(lineSeparator);
			sb.append("请求方法 :").append(executeClass+"."+executeMethod).append(lineSeparator);
			Object[] args = joinPoint.getArgs();
			if (args != null && args.length > 0) {
				sb.append("请求参数 :");
				String requestParam = JSONUtil.toJsonStr(args);
				sb.append(requestParam);
				sb.append(lineSeparator);
			}
			sb.append("*********************************请求信息结束***************************************");
			for (int i = 0; i < 10; i++) {
				StaticLog.info(sb.toString());
			}
		} catch (Exception e1) {
			StaticLog.warn(e1, "前置通知执行异常");
		}
	}

	/**
	 *
	 * @param ret
	 * @throws Throwable
	 */
	@AfterReturning(returning = "ret", pointcut = "webLog()")
	public void doAfterReturning(Object ret) throws Throwable {
		if (ret != null) {
			JSONObject json = JSONUtil.parseObj(ret);
			String result = json.toString();
			for (int i = 0; i < 10; i++) {
				StaticLog.info("方法的返回值 :  {}", result);
			}
		}
	}

	/**
	 *
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("webLog()")
	public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
		Object obj;
		long startTime = System.currentTimeMillis();
		obj = joinPoint.proceed(joinPoint.getArgs());
		long endTime = System.currentTimeMillis() - startTime;
		String classAndMethod = joinPoint.getSignature().getDeclaringTypeName() + "."
				+ joinPoint.getSignature().getName();
		for (int i = 0; i < 10; i++) {
			StaticLog.info("执行{}耗时为：{} ms", classAndMethod, endTime);
		}
		return obj;
	}
}
